/*******************************************************************************
 (c) 2005-2014 Copyright, Real-Time Innovations, Inc.  All rights reserved.
 RTI grants Licensee a license to use, modify, compile, and create derivative
 works of the Software.  Licensee has the right to distribute object form only
 for use with RTI products.  The Software is provided "as is", with no warranty
 of any type, including any warranty for fitness for any purpose. RTI is under
 no obligation to maintain or support the Software.  RTI shall not be liable for
 any incidental or consequential damages arising out of the use or inability to
 use the software.
 ******************************************************************************/
using System;
using System.Collections.Generic;
using System.Text;
/* sequences_publisher.cs

   A publication of data of type sequences

   This file is derived from code automatically generated by the rtiddsgen 
   command:

   rtiddsgen -language C# -example <arch> sequences.idl

   Example publication of type sequences automatically generated by 
   'rtiddsgen'. To test them follow these steps:

   (1) Compile this file and the example subscription.

   (2) Start the subscription with the command
       objs\<arch>\sequences_subscriber <domain_id> <sample_count>
                
   (3) Start the publication with the command
       objs\<arch>\sequences_publisher <domain_id> <sample_count>

   (4) [Optional] Specify the list of discovery initial peers and 
       multicast receive addresses via an environment variable or a file 
       (in the current working directory) called NDDS_DISCOVERY_PEERS. 

   You can run any number of publishers and subscribers programs, and can 
   add and remove them dynamically from the domain.


   Example:

       To run the example application on domain <domain_id>:

       bin\<Debug|Release>\sequences_publisher <domain_id> <sample_count>
       bin\<Debug|Release>\sequences_subscriber <domain_id> <sample_count>

       
modification history
------------ -------       
*/

public class sequencesPublisher {

    public static void Main( string[] args ) {

        // --- Get domain ID --- //
        int domain_id = 0;
        if (args.Length >= 1) {
            domain_id = Int32.Parse(args[0]);
        }

        // --- Get max loop count; 0 means infinite loop  --- //
        int sample_count = 0;
        if (args.Length >= 2) {
            sample_count = Int32.Parse(args[1]);
        }

        /* Uncomment this to turn on additional logging
        NDDS.ConfigLogger.get_instance().set_verbosity_by_category(
            NDDS.LogCategory.NDDS_CONFIG_LOG_CATEGORY_API, 
            NDDS.LogVerbosity.NDDS_CONFIG_LOG_VERBOSITY_STATUS_ALL);
        */

        // --- Run --- //
        try {
            sequencesPublisher.publish(
                domain_id, sample_count);
        } catch (DDS.Exception) {
            Console.WriteLine("error in publisher");
        }
    }

    static void publish( int domain_id, int sample_count ) {

        // --- Create participant --- //

        /* To customize participant QoS, use 
           the configuration file USER_QOS_PROFILES.xml */
        DDS.DomainParticipant participant =
            DDS.DomainParticipantFactory.get_instance().create_participant(
                domain_id,
                DDS.DomainParticipantFactory.PARTICIPANT_QOS_DEFAULT,
                null /* listener */,
                DDS.StatusMask.STATUS_MASK_NONE);
        if (participant == null) {
            shutdown(participant);
            throw new ApplicationException("create_participant error");
        }

        // --- Create publisher --- //

        /* To customize publisher QoS, use 
           the configuration file USER_QOS_PROFILES.xml */
        DDS.Publisher publisher = participant.create_publisher(
        DDS.DomainParticipant.PUBLISHER_QOS_DEFAULT,
        null /* listener */,
        DDS.StatusMask.STATUS_MASK_NONE);
        if (publisher == null) {
            shutdown(participant);
            throw new ApplicationException("create_publisher error");
        }

        // --- Create topic --- //

        /* Register type before creating topic */
        System.String type_name = sequencesTypeSupport.get_type_name();
        try {
            sequencesTypeSupport.register_type(
                participant, type_name);
        } catch (DDS.Exception e) {
            Console.WriteLine("register_type error {0}", e);
            shutdown(participant);
            throw e;
        }

        /* To customize topic QoS, use 
           the configuration file USER_QOS_PROFILES.xml */
        DDS.Topic topic = participant.create_topic(
            "Example sequences",
            type_name,
            DDS.DomainParticipant.TOPIC_QOS_DEFAULT,
            null /* listener */,
            DDS.StatusMask.STATUS_MASK_NONE);
        if (topic == null) {
            shutdown(participant);
            throw new ApplicationException("create_topic error");
        }

        // --- Create writer --- //

        /* To customize data writer QoS, use 
           the configuration file USER_QOS_PROFILES.xml */
        DDS.DataWriter writer = publisher.create_datawriter(
            topic,
            DDS.Publisher.DATAWRITER_QOS_DEFAULT,
            null /* listener */,
            DDS.StatusMask.STATUS_MASK_NONE);
        if (writer == null) {
            shutdown(participant);
            throw new ApplicationException("create_datawriter error");
        }
        sequencesDataWriter sequences_writer =
            (sequencesDataWriter)writer;

        /* Here we define two instances: owner_instance and borrower_instance.*/

        /* owner_instance.data uses its own memory, as by default, a sequence
         * you create owns its memory unless you explicitly loan memory of your
         * own to it.
         */

        sequences owner_instance = sequencesTypeSupport.create_data();
        sequences borrower_instance = sequencesTypeSupport.create_data();

        DDS.InstanceHandle_t owner_instance_handle =
                    DDS.InstanceHandle_t.HANDLE_NIL;
        DDS.InstanceHandle_t borrower_instance_handle =
                 DDS.InstanceHandle_t.HANDLE_NIL;

        /* If we want borrower_instance.data to loan a buffer of shorts, 
         * first we have to allocate the buffer. Here we allocate a buffer 
         * of MAX_SEQUENCE_LEN. */

        short[] short_buffer = new short[MAX_SEQUENCE_LEN.VALUE];
        /* Before calling loan(), we need to set sequence maximum to 0, 
         * i.e., the sequence won't have memory allocated to it. */
        borrower_instance.data.maximum = 0;

        /* Now that the sequence doesn't have memory allocated to it, we can
         * call loan() to loan shortBuffer to borrowerInstance.
         * We set the allocated number of elements to MAX_SEQUENCE_LEN, the 
         * size of the buffer and the maximum size of the sequence as we 
         * declared in the IDL. */
        borrower_instance.data.loan(
            short_buffer, //Buffer
            0); //Initial length

        /* Before starting to publish samples, set the instance id of each
         * instance*/
        owner_instance.id = "owner_instance";
        borrower_instance.id = "browser_instance";

        /*
        instance_handle = sequences_writer.register_instance(instance);
        */

        /* We use Random to generate random values for the sequences */
        Random random = new Random();

        /* Main loop */
        /* To illustrate the use of the sequences, in the main loop we set a
         * new sequence length every iteration to the sequences contained in
         * both instances (instance.data). The sequence length value cycles
         * between 0 and MAX_SEQUENCE_LEN. We assign a random number between
         * 0 and 100 to each sequence's elements. */
        const System.Int32 send_period = 1000; // milliseconds
        for (int count = 0;
             (sample_count == 0) || (count < sample_count);
             ++count) {
            /* We set a different sequenceLength for both instances every
             * iteration. sequenceLength is based on the value of count 
             * and its value cycles between the values of 1 and 
             * MAX_SEQUENCE_LEN. */
            int sequence_length = (count % MAX_SEQUENCE_LEN.VALUE) + 1;

            Console.WriteLine("Writing sequences, count {0}...", count);

            owner_instance.count = (short)count;
            borrower_instance.count = (short)count;

            /* Here we set the new length of each sequence */
            owner_instance.data.length = sequence_length;
            borrower_instance.data.length = sequence_length;

            /* Now that the sequences have a new length, we assign a
             * random number between 0 and 100 to each element of
             * owner_instance->data and borrower_instance->data. */
            for (int i = 0; i < sequence_length; ++i) {
                owner_instance.data.set_at(i, (short)random.Next(0, 100));
                borrower_instance.data.set_at(i, (short)random.Next(0, 100));
            }

            /* Both sequences have the same length, so we only print the length
             * of one of them. */
            Console.WriteLine("Instances length = {0}", 
                owner_instance.data.length);

            /* Write for each instance */

            try {
                sequences_writer.write(owner_instance, 
                    ref owner_instance_handle);
            } catch (DDS.Exception e) {
                Console.WriteLine("write error {0}", e);
            }

            try {
                sequences_writer.write(borrower_instance,
                    ref borrower_instance_handle);
            } catch (DDS.Exception e) {
                Console.WriteLine("write error {0}", e);
            }


            System.Threading.Thread.Sleep(send_period);
        }

        /* Once we are done with the sequence, we call unloan() */
        borrower_instance.data.unloan();

        /*
        try {
            sequences_writer.unregister_instance(
                instance, ref instance_handle);
        } catch(DDS.Exception e) {
            Console.WriteLine("unregister instance error: {0}", e);
        }
        */

        // --- Shutdown --- //

        /* Delete data sample */
        try {
            sequencesTypeSupport.delete_data(owner_instance);
        } catch (DDS.Exception e) {
            Console.WriteLine(
                "sequencesTypeSupport.delete_data error: {0}", e);
        }

        /* Delete all entities */
        shutdown(participant);
    }

    static void shutdown(
        DDS.DomainParticipant participant ) {

        /* Delete all entities */

        if (participant != null) {
            participant.delete_contained_entities();
            DDS.DomainParticipantFactory.get_instance().delete_participant(
                ref participant);
        }

        /* RTI Connext provides finalize_instance() method on
           domain participant factory for people who want to release memory
           used by the participant factory. Uncomment the following block of
           code for clean destruction of the singleton. */
        /*
        try {
            DDS.DomainParticipantFactory.finalize_instance();
        } catch (DDS.Exception e) {
            Console.WriteLine("finalize_instance error: {0}", e);
            throw e;
        }
        */
    }
}

